package com.two.auth.config;

import com.alibaba.fastjson.JSON;
import com.two.auth.feign.SystemFeign;
import com.two.auth.service.MyUserService;
import com.two.core.entity.AclUser;
import com.two.core.util.JWTUtil;
import com.two.core.vo.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author ：lushimin（2741890790@qq.com）
 * @date ：Created in 2022/11/1 19:30
 * @description：
 * @modified By：
 * @version:
 */
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private MyUserService userService;
    @Autowired
    private SystemFeign systemFeign;
    //重写父类得两个方法。
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //设置登录表单得规则
        http.formLogin()
                //如果登录成功执行得函数
                .successHandler(successHandler())
                //登录失败执行得函数
                .failureHandler(failureHandler())
                //放行
                .permitAll();
        //设置security允许登录跨域
        http.cors();
        //关闭跨域伪造请求.
        http.csrf().disable();
        //其他所有得请求都需要认证。
        http.authorizeRequests().anyRequest().authenticated();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().mvcMatchers("/doc.html");
    }

    //登录成功
    private AuthenticationSuccessHandler successHandler(){
        return (request, response, authentication) -> {
            response.setContentType("application/json;charset=utf-8");
            PrintWriter writer = response.getWriter();
            //生产token---userid+permission----JWT.
            //获取登录成功后用户对象。
            User user = (User) authentication.getPrincipal();
            //登录成功得账户
            String username = user.getUsername();
            //获取登录成功得账户具有得权限
            Collection<GrantedAuthority> authorities = user.getAuthorities();
            List<String> permissions=authorities.stream()
                    .filter(item->item.getAuthority()!=null)
                    .map(item->item.getAuthority()).collect(Collectors.toList());
            // 获取到id
            Result<AclUser> byName = systemFeign.getByName(username);
            Map<String,Object> map=new HashMap<>();
            // 存放用户id
            map.put("userId",byName.getData().getId());
            map.put("username",username);
            map.put("permissions",permissions);
            //按照账户和权限生产token
            String token = JWTUtil.createJWT(map);

            //封装到响应对象中
            Result result=new Result(2000,"登录成功",token);
            String jsonString = JSON.toJSONString(result);
            writer.print(jsonString);

            writer.flush();
            writer.close();
        };
    }

    //登录失败执行得方法
    private AuthenticationFailureHandler failureHandler() {
        return (request, response, e) -> {
            response.setContentType("application/json;charset=utf-8");
            PrintWriter writer = response.getWriter();

            Result result=new Result(5000,"账户或密码错误");
            String jsonString = JSON.toJSONString(result);
            writer.print(jsonString);
            writer.flush();
            writer.close();
        };
    }

    public static void main(String[] args) {
        BCryptPasswordEncoder bCryptPasswordEncoder=new BCryptPasswordEncoder();
        String encode = bCryptPasswordEncoder.encode("123456");
        System.out.println("encode = " + encode);
    }
}
